﻿// Decompiled with JetBrains decompiler
// Type: System.Web.Razor.Parser.ParserContext
// Assembly: System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// MVID: 682513D6-F37E-48AC-9909-F3EE103CFF14
// Assembly location: D:\Project\Idea\无人机外网\uav\客户端工程\排查工具\bin\Release\System.Web.Razor.dll

using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Razor.Parser.SyntaxTree;
using System.Web.Razor.Resources;
using System.Web.Razor.Text;
using System.Web.Razor.Utils;

namespace System.Web.Razor.Parser
{
  /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Represents a parser whose context can be switched to either a code or a markup.</summary>
  public class ParserContext
  {
    private int? _ownerTaskId;
    private bool _terminated;
    private Stack<BlockBuilder> _blockStack = new Stack<BlockBuilder>();

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Initializes a new instance of the <see cref="T:System.Web.Razor.Parser.ParserContext" /> class.</summary>
    /// <param name="source">The source document.</param>
    /// <param name="codeParser">The code parser for the context.</param>
    /// <param name="markupParser">The markup parser for the context.</param>
    /// <param name="activeParser">The active parser for the context.</param>
    public ParserContext(
      ITextDocument source,
      ParserBase codeParser,
      ParserBase markupParser,
      ParserBase activeParser)
    {
      if (source == null)
        throw new ArgumentNullException(nameof (source));
      if (codeParser == null)
        throw new ArgumentNullException(nameof (codeParser));
      if (markupParser == null)
        throw new ArgumentNullException(nameof (markupParser));
      if (activeParser == null)
        throw new ArgumentNullException(nameof (activeParser));
      if (activeParser != codeParser && activeParser != markupParser)
        throw new ArgumentException(RazorResources.ActiveParser_Must_Be_Code_Or_Markup_Parser, nameof (activeParser));
      this.Source = new TextDocumentReader(source);
      this.CodeParser = codeParser;
      this.MarkupParser = markupParser;
      this.ActiveParser = activeParser;
      this.Errors = (IList<RazorError>) new List<RazorError>();
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets the list of errors during parsing.</summary>
    /// <returns>The list of errors.</returns>
    public IList<RazorError> Errors { get; private set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets the text reader for the source document.</summary>
    /// <returns>The text reader for the source document.</returns>
    public TextDocumentReader Source { get; set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets the code parser for the context.</summary>
    /// <returns>The code parser for the context.</returns>
    public ParserBase CodeParser { get; private set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets the markup parser for the context.</summary>
    /// <returns>The markup parser for the context.</returns>
    public ParserBase MarkupParser { get; private set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets the active parser for the context.</summary>
    /// <returns>The active parser for the context.</returns>
    public ParserBase ActiveParser { get; private set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets a value that indicates whether the parser is in design mode.</summary>
    /// <returns>true if the parser is in design mode; otherwise, false.</returns>
    public bool DesignTimeMode { get; set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets the current block builder.</summary>
    /// <returns>The current block builder.</returns>
    public BlockBuilder CurrentBlock => this._blockStack.Peek();

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets the last span.</summary>
    /// <returns>The last span.</returns>
    public Span LastSpan { get; private set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets a value that indicates whether white space is significant to ancestor block.</summary>
    /// <returns>true is white space is significant to ancestor block; otherwise, false.</returns>
    public bool WhiteSpaceIsSignificantToAncestorBlock { get; set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets the last accepted characters.</summary>
    /// <returns>One of the values of the <see cref="T:System.Web.Razor.Parser.SyntaxTree.AcceptedCharacters" /> enumeration.</returns>
    public AcceptedCharacters LastAcceptedCharacters => this.LastSpan == null ? AcceptedCharacters.None : this.LastSpan.EditHandler.AcceptedCharacters;

    internal Stack<BlockBuilder> BlockStack => this._blockStack;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets the current character available from the source.</summary>
    /// <returns>The current character available from the source.</returns>
    public char CurrentCharacter
    {
      get
      {
        if (this._terminated)
          return char.MinValue;
        int num = this.Source.Peek();
        return num == -1 ? char.MinValue : (char) num;
      }
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets a value that indicates whether the source status is end of file.</summary>
    /// <returns>true if the source status is end of file; otherwise, false.</returns>
    public bool EndOfFile => this._terminated || this.Source.Peek() == -1;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Adds the specified span at the end of the block builder stack.</summary>
    /// <param name="span">The span to add.</param>
    public void AddSpan(Span span)
    {
      this.EnusreNotTerminated();
      if (this._blockStack.Count == 0)
        throw new InvalidOperationException(RazorResources.ParserContext_NoCurrentBlock);
      this._blockStack.Peek().Children.Add((SyntaxTreeNode) span);
      this.LastSpan = span;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Adds a new block builder at the end of the block builder stack and returns a disposable action that returns an end block.</summary>
    /// <returns>A disposable action that returns an end block.</returns>
    /// <param name="blockType">The type for the new block builder.</param>
    public IDisposable StartBlock(BlockType blockType)
    {
      this.EnusreNotTerminated();
      this._blockStack.Push(new BlockBuilder()
      {
        Type = new BlockType?(blockType)
      });
      return (IDisposable) new DisposableAction(new Action(this.EndBlock));
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Adds a new block builder at the end of the block builder stack and returns a disposable action that returns an end block.</summary>
    /// <returns>A disposable action that returns an end block.</returns>
    public IDisposable StartBlock()
    {
      this.EnusreNotTerminated();
      this._blockStack.Push(new BlockBuilder());
      return (IDisposable) new DisposableAction(new Action(this.EndBlock));
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Creates an end block from the last item of the block builder stack. </summary>
    public void EndBlock()
    {
      this.EnusreNotTerminated();
      if (this._blockStack.Count == 0)
        throw new InvalidOperationException(RazorResources.EndBlock_Called_Without_Matching_StartBlock);
      if (this._blockStack.Count > 1)
      {
        BlockBuilder blockBuilder = this._blockStack.Pop();
        this._blockStack.Peek().Children.Add((SyntaxTreeNode) blockBuilder.Build());
      }
      else
        this._terminated = true;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Determines whether the specified block type exists in the block builder list.</summary>
    /// <returns>true if the specified block type exists in the block builder list; otherwise, false.</returns>
    /// <param name="type">The block type to check.</param>
    public bool IsWithin(BlockType type) => this._blockStack.Any<BlockBuilder>((Func<BlockBuilder, bool>) (b =>
    {
      BlockType? type1 = b.Type;
      BlockType blockType = type;
      return type1.GetValueOrDefault() == blockType & type1.HasValue;
    }));

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Alternately switches the code parser or markup parser as the active parser.</summary>
    public void SwitchActiveParser()
    {
      this.EnusreNotTerminated();
      if (this.ActiveParser == this.CodeParser)
        this.ActiveParser = this.MarkupParser;
      else
        this.ActiveParser = this.CodeParser;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Occurs when parse encountered error.</summary>
    /// <param name="location">The source location.</param>
    /// <param name="message">The error message.</param>
    public void OnError(SourceLocation location, string message)
    {
      this.EnusreNotTerminated();
      this.Errors.Add(new RazorError(message, location));
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Occurs when parse encountered an error.</summary>
    /// <param name="location">The source location.</param>
    /// <param name="message">The error message.</param>
    /// <param name="args">The other information about the source location.</param>
    public void OnError(SourceLocation location, string message, params object[] args)
    {
      this.EnusreNotTerminated();
      this.OnError(location, string.Format((IFormatProvider) CultureInfo.CurrentCulture, message, args));
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Parses the last span and returns the parse results that contain the newly built block.</summary>
    /// <returns>The parse results that contain the newly built block.</returns>
    public ParserResults CompleteParse()
    {
      if (this._blockStack.Count == 0)
        throw new InvalidOperationException(RazorResources.ParserContext_CannotCompleteTree_NoRootBlock);
      return this._blockStack.Count == 1 ? new ParserResults(this._blockStack.Pop().Build(), this.Errors) : throw new InvalidOperationException(RazorResources.ParserContext_CannotCompleteTree_OutstandingBlocks);
    }

    [Conditional("DEBUG")]
    internal void CaptureOwnerTask()
    {
      if (!Task.CurrentId.HasValue)
        return;
      this._ownerTaskId = Task.CurrentId;
    }

    [Conditional("DEBUG")]
    internal void AssertOnOwnerTask()
    {
      int num = this._ownerTaskId.HasValue ? 1 : 0;
    }

    [Conditional("DEBUG")]
    internal void AssertCurrent(char expected)
    {
    }

    private void EnusreNotTerminated()
    {
      if (this._terminated)
        throw new InvalidOperationException(RazorResources.ParserContext_ParseComplete);
    }
  }
}
